# -*- coding: utf-8 -*-
import datetime
from pyshare.utils.time_utils import getCT
from pyshare.bll.errors import ChargingError


class TravelMixin(object):
    """
    冷却时间固定，恢复数值不为1的倒计时方法类，
    使用base_time记录开始倒计时时间
    """
    __slots__ = ()

    # 上限值
    capacity = NotImplemented
    # 倒计时时间
    base_time = NotImplemented
    # 冷却期
    cooldown_period = NotImplemented
    # 周期恢复值
    add_value = NotImplemented
    # 记录值
    record = NotImplemented

    @property
    def remaining(self):
        """剩余可用次数。
        
        若满N次冷却期则恢复N次add_value，并重置倒计时时间
        超过上限取上限值

        :rtype: int
        """
        # 若超出上限则直接返回
        if self.record <= self.capacity:
            a = (getCT() - self.base_time).total_seconds()
            b = self.cooldown_period.total_seconds()
            c = int(a // b)

            r = self.record + self.add_value * c
            self.base_time += self.cooldown_period * c

            self.record = min(self.capacity, r)
        return self.record

    @remaining.setter
    def remaining(self, value):
        """修改剩余可用次数。"""
        # 若为第一次使用或道具恢复则更新倒计时时间
        if self.isfull():
            self.base_time = getCT()

        if value < 0:
            raise ChargingError('out of capacity')
        # elif value > self.capacity:
        #     self.record = self.capacity
        else:
            self.record = value

    @property
    def used(self):
        """已使用的次数。

        :rtype: int
        """
        return self.capacity - self.remaining

    def isfull(self):
        """可用次数是否已满。

        :rtype: bool
        """
        return self.remaining >= self.capacity

    def isempty(self):
        """可用次数是否为 0 。

        :rtype: bool
        """
        return self.remaining == 0

    def ischarging(self):
        """是否正在补充。

        :rtype: bool
        """
        return not self.isfull()

    def refill(self):
        """补充全部次数。"""
        self.remaining = self.capacity

    def charged_period(self):
        """当前补充已进行的时间。

        :rtype: datetime.timedelta
        """
        if not self.ischarging():
            raise ChargingError('not charging')

        a = (getCT() - self.base_time).total_seconds()
        b = self.cooldown_period.total_seconds()
        t = datetime.timedelta(seconds=(a % b))
        return t

    def charge_at(self):
        """当前补充完成的时刻。

        :rtype: datetime.datetime
        """
        return datetime.datetime.now() + self.waiting_period()

    def waiting_period(self):
        """距当前补充完成仍需等待的时间。

        :rtype: datetime.timedelta
        """
        if not self.ischarging():
            raise ChargingError('not charging')

        return self.cooldown_period - self.charged_period()

    def asdict(self):
        d = {
            'Remaining': self.remaining,
            'MaxRounds': self.capacity,
        }

        if self.ischarging():
            d['ChargeAt'] = self.charge_at()

        return d

if __name__ == '__main__':

    class Traveltest(TravelMixin):
        def __init__(self):
            self.capacity = 15
            self.cooldown_period = datetime.timedelta(seconds=10)
            self.base_time = datetime.datetime.fromtimestamp(0)
            self.record = 15
            self.add_value = 5

    obj = Traveltest()
    print 'remaining: %d, record: %d, base_time: %s' % (obj.remaining, obj.record, obj.base_time)

    obj.remaining -= 1
    obj.record = obj.remaining
    print '使用一次，remaining: %d, record: %d, base_time: %s' % (obj.remaining, obj.record, obj.base_time)

    import time
    time.sleep(8)
    print '恢复八秒，remaining: %d, record: %d, base_time: %s' % (obj.remaining, obj.record, obj.base_time)

    obj.remaining -= 5
    print '使用五次remaining: %d, record: %d, base_time: %s' % (obj.remaining, obj.record, obj.base_time)
    print obj.isempty(), obj.waiting_period()

    time.sleep(5)
    print '恢复五秒，remaining: %d, record: %d, base_time: %s' % (obj.remaining, obj.record, obj.base_time)

    time.sleep(7)
    print '恢复7秒，remaining: %d, record: %d, base_time: %s' % (obj.remaining, obj.record, obj.base_time)

    # time.sleep(5)
    # obj.remaining -= 5
    # print '使用五次，remaining: %d, record: %d, base_time: %s' % (obj.remaining, obj.record, obj.base_time)

    obj.remaining += 8
    print '增加8次，remaining: %d, record: %d, base_time: %s' % (obj.remaining, obj.record, obj.base_time)

    obj.remaining = 0
    print '设置体力为0，remaining: %d, record: %d, base_time: %s' % (obj.remaining, obj.record, obj.base_time)

    print obj.isempty(), obj.waiting_period()

    time.sleep(5.5)

    obj.remaining += 20
    print '增加20次，remaining: %d, record: %d, base_time: %s' % (obj.remaining, obj.record, obj.base_time)
